<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <!-- 
    1.app.message修改数据,Vue内容是如何监听message数据的改变
    * Object.defineProperty -> 监听对象属性的改变
    2.当数据发生改变,Vue是如何知道要通知哪些人的,界面发生刷新
    * 发布订阅者模式
   -->
  <div id="app">
    {{message}}
    {{message}}
    {{message}}
    {{name}}
  </div>

  <script>
    const obj = {
      message: '哈哈哈',
      name: 'why'
    }

    // 可以拿到一个keys的数组 ['message','name']
    Object.keys(obj).forEach(key => {
      let value = obj[key]
      // 给某一个对象定义属性 Object.defineProperty(对象,键,值)
      Object.defineProperty(obj, key, {
        set(newValue) {
          console.log('监听' + key + '改变');
          // 告诉谁了? 谁用告诉谁 
          // 谁在用了? 根据解析html代码,获取到哪些人有用属性,解析到谁用,谁就去用get
          value = newValue

          dep.notify()
        },
        get() {
          console.log('获取' + key + '对应的值');
          // get使用了,就知道谁用了,到时候就通知谁
          // div1: get -> update
          // div2: get -> update
          // div3: get -> update
          return value
        }
      })
    })

    // 发布者/订阅者模式

    // 发布者
    class Dep {
      constructor() {
        // 
        this.subs = []
      }
      addSub(watcher) {
        this.subs.push(watcher)
      }
      notify() {
        this.subs.forEach(item => {
          item.update()
        })
      }
    }

    // 订阅者
    class Watcher {
      constructor(name) {
        this.name = name;
      }
      update() {
        console.log(this.name + '发生update');
      }
    }

    const dep = new Dep()
    const watcher1 = new Watcher('div1')
    dep.addSub(watcher1)

    const watcher2 = new Watcher('div2')
    dep.addSub(watcher2)

    const watcher3 = new Watcher('div3')
    dep.addSub(watcher3)

    dep.notify()
  </script>

  <script src="../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        message: '哈哈哈',
        name: 'why'
      }
    })
  </script>

</body>

</html>